﻿/*********************************************
Copyright (c) 2013 All Right Reserved, bixaps

This source is subject to the Microsoft Permissive License.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Author: Raj Bandi
Email: raj.bandi@hotmail.com

Numeric textbox control
*********************************************/

(function () {
    "use strict";

    WinJS.Namespace.define("Bixaps.UI",
        {
            NumericBox: WinJS.Class.define(function (element, options) {
                
                element = element || document.createElement("span");
                this._options = options || {};
                element.winControl = this;
                WinJS.UI.setOptions(this, options);
                this._init(element);

            }, {
                _min: null,
                _max:null,
                _step: 1,
                _placeHolder: '',
                _format: null,
                _value: null,
                _stepDirection: 1,
                _decimalPlaces: 2,
                _hasFocus:false,
                _valueChanged:false,
                _mouseTimer: null,
                _icons:null,
                _iconsCssClass:null,
                _init: function (element) {
                    this._setElement(element);
                    //this._refresh();
                    this._displayFormat(true);
                },
               _setElement: function (element) {

                   if (element instanceof HTMLInputElement) {
                       this._domElement = document.createElement("span");
                       this._inputElement = element;
                       this._domElement.winControl = this;
                       delete element.winControl;
                   } else {
                       this._domElement = element;
                       WinJS.Utilities.empty(this._domElement);
                       this._inputElement = document.createElement("input");
                   }
                   this._inputElement.setAttribute("type", "number");

                   this._upElement = document.createElement("a");
                   this._downElement = document.createElement("a");

                   if (!this._domElement) { return; }
                
                   if (this._inputElement.parentNode != null) {
                       this._inputElement.parentNode.insertBefore(this._domElement, this._inputElement);
                   }

                   this._upButton = document.createElement("span");
                   this._downButton = document.createElement("span");
                   
                   this._refreshIcons();
                   
                   WinJS.Utilities.addClass(this._domElement, "win-numericbox");
                   WinJS.Utilities.addClass(this._inputElement, "win-numericbox-input");
                   WinJS.Utilities.addClass(this._upElement, "win-numericbox-button win-numericbox-up");
                   WinJS.Utilities.addClass(this._downElement, "win-numericbox-button win-numericbox-down");
                   WinJS.Utilities.addClass(this._upButton, "win-numericbox-up-icon");
                   WinJS.Utilities.addClass(this._downButton, "win-numericbox-down-icon");
                   
                   this._upElement.appendChild(this._upButton);
                   this._downElement.appendChild(this._downButton);
                   
                   this._domElement.appendChild(this._inputElement);
                   this._domElement.appendChild(this._downElement);
                   this._domElement.appendChild(this._upElement);

                   var that = this;

                   var mouseTimer;
                   this._upElement.addEventListener("mousedown",function(e) {
                       that._updateValue();
                       mouseTimer = setInterval(that.stepUp(), 100);
                      
                   });
                   
                   this._upElement.addEventListener("mouseup", function (e) {
                      clearInterval(mouseTimer);
                   });

                   this._downElement.addEventListener("mousedown", function () {
                       that._updateValue();
                       mouseTimer = setInterval(that.stepDown(), 100);
                   });

                   this._downElement.addEventListener("mouseup", function () {
                       clearInterval(mouseTimer);
                   });

                   this._inputElement.addEventListener("focus", function (e) {
                       that._onFocus(e);
                   });
                   this._inputElement.addEventListener("blur", function (e) {
                       that._onBlur(e);
                   });

                   this._inputElement.addEventListener("keydown", function(e) {
                       that._inputKeyDown(e);
                     
                   });
                   
                   this._inputElement.addEventListener("mousewheel", function (e) {
                       that._inputMouseWheel(e);
                   });
                   
                   if (this._min != null) {
                       this._value = this._min;
                       //this._inputElement.value = this._min;
                   }
                   
                   setTimeout(function() {
                       that._adjustDimensions();
                   }, 10);

                 

               },
               _adjustDimensions: function () {
                   
                   var h = WinJS.Utilities.getContentHeight(this._inputElement);

                   var style = document.defaultView.getComputedStyle(this._inputElement);

                   var t = eval(h);
                   if (style.marginTop) {
                       var m = style.marginTop.replace("px", "");
                       t += eval(m);
                   }
                   if (style.borderTop) {
                       var b = style.borderTop.replace("px", "");
                       t += eval(b);
                   }
                   this._upElement.style.lineHeight = h + "px";
                   this._downElement.style.lineHeight = h + "px";
                   this._upElement.style.height = t + "px";
                   this._downElement.style.height = t + "px";
               },
               _updateDisplay: function (reset) {
                   this._adjustValue();
                   this._refresh();
                   this._displayFormat(reset);
               },
               _swapValue: function () {
                   this._valueChanged = false;

                   this._inputElement.value = this._value;
                   this._inputElement.defaultValue = this._value;
                   this._inputElement.setAttribute('placeholder', '');
               },
               _displayFormat: function (reset) {
                  
                   if (!this._inputElement)
                       return;
                   var val = this._value;
                   if (reset) {
                       this._inputElement.value = '';
                   }
                   this._inputElement.defaultValue = val;
                   if ( !isNaN(val)) {
                       val = this._adjustDecimals(val);
                       var formatStr = val;

                       if (this._format != null && this._format.length > 0) {

                           switch (this._format.charAt(0).toLowerCase()) {
                               case 'c':
                                   formatStr = '$' + val;
                                   break;
                               case 'p':
                                   formatStr = val + '%';
                                   break;
                               case 'e':
                                   formatStr = val + 'e+0';
                                   break;
                           }
                       }
                       this._inputElement.setAttribute("placeholder", formatStr);
                   }
               },
               _refresh: function () {
                   if (this._inputElement != null) {
                       this._inputElement.value = this._value;
                      
                   }
               },
               _updateValue: function () {
                   
                   if (this._valueChanged) {
                       if (!isNaN(this._inputElement.value)) {
                           if (this._inputElement.defaultValue != this._inputElement.value)
                           {
                               var val = this._inputElement.value;
                               val = this._adjustDecimals(val);
                               this._value = val;
                               this._checkValue();
                               this._valueChanged = false;

                           } 
                       }
                   }
               },
               _checkValue: function () {
                   var origValue = this._value;
                   var val = origValue;
                   if (val != null) {
                       if (this._min != null) {
                           if (val < this._min)
                               val = this._min;
                       }
                       if (this._max != null && val > this._max) {
                           val = this._max;
                       }
                       //if (val != origValue) {
                           this._value = val;
                       //}
                   }
               },
               _adjustDecimals: function (val) {
                   if (val && !isNaN(val)) {
                       val = eval(val);
                       var checkValDecimal = val % 1 != 0;
                       var checkStepDecimal = this._step % 1 != 0;
                       
                       if (checkValDecimal || checkStepDecimal) {
                            val = val.toFixed(this._decimalPlaces || 0);
                       }
                   }
                   return val;
               },
               _adjustValue: function () {
                   var val = this._value || 0;
                   if (val != null) {
                       val = eval(val) + (this._stepDirection * this._step);
                       val = this._adjustDecimals(val);
                       this._value = val;
                   }
                   this._checkValue();
               },
               _inputKeyDown: function(e) {
                   var keys = Bixaps.Util.Keys;
                   var code = e.keyCode;
                   if (code == keys.UP) {
                       this._stepUp(false);
                   } else if (code == keys.DOWN)
                   {
                       this._stepDown(false);
                   } 
               
                   if((code>=47 && code<=57) || code==190 || code==8 || code==46)
                   {
                       this._valueChanged = true;
                   }
                   return true;
               },
                _inputMouseWheel: function( e) {
                    if (!this._hasFocus) {
                        console.log('focus');
                        this._inputElement.focus();
                        this._hasFocus = true;
                    }
                    if (e.wheelDelta > 0) {
                        
                        this._stepUp(false);
                      
                    }
                    else {
                        this._stepDown(false);
                      
                    }
                   
                },
                _onFocus:function (e) {
                    this._valueChanged = false;
                    this._hasFocus = true;
                    this._refresh();
                },
                _onBlur:function (e) {
                    this._hasFocus = false;
                    this._updateValue();
                    this._displayFormat(true);

                },
               _stepUp:function(reset) {
                   this._stepDirection = 1;
                   this._updateDisplay(reset);
                   this._onStep();
                   this._onStepDown();
               },
                _stepDown:function(reset) {
                    this._stepDirection = -1;
                    this._updateDisplay(reset);
                    this._onStep();
                    this._onStepUp();
                },
               _onStep: function () {
                    var eventObject = document.createEvent("CustomEvent");
                    eventObject.initCustomEvent("step", false, false, {"control":this});
                    this._domElement.dispatchEvent(eventObject);
               },
               _onStepUp: function () {
                   var eventObject = document.createEvent("CustomEvent");
                   eventObject.initCustomEvent("stepup", false, false, { "control": this });
                   this._domElement.dispatchEvent(eventObject);
               },
               _onStepDown: function () {
                   var eventObject = document.createEvent("CustomEvent");
                   eventObject.initCustomEvent("stepdown", false, false, { "control": this });
                   this._domElement.dispatchEvent(eventObject);
               },
               _refreshIcons:function () {
                 
                   if (!this.iconsCssClass) {
                       if (!this._icons) {
                           this._icons = {
                               up: Bixaps.Util.Icons.ARROW_HEAD_UP,
                               down: Bixaps.Util.Icons.ARROW_HEAD_DOWN
                           };
                       }
                       
                       if (this._icons.up && this._icons.up.indexOf('data:image') >= 0
                           || this._icons.up.indexOf('.jpg')
                           || this._icons.up.indexOf('.png')) {
                           var img = document.createElement('img');
                           img.src = this._icons.up;
                           
                           this._upButton.innerHTML = '';
                           this._upButton.appendChild(img);
                       } else {
                           this._upButton.innerHTML = window.toStaticHTML(this._icons.up);
                       }
                       
                       if (this._icons.up && this._icons.down.indexOf('data:image') >= 0
                         || this._icons.down.indexOf('.jpg')
                         || this._icons.down.indexOf('.png')) {
                           var img = document.createElement('img');
                           img.src = this._icons.down;
                           
                           this._downButton.innerHTML = '';
                           this._downButton.appendChild(img);
                       } else {
                           this._downButton.innerHTML = window.toStaticHTML(this._icons.down);

                       }
                      
                   } else {

                       WinJS.Utilities.addClass(this._upButton, this._iconsCssClass.up);
                       WinJS.Utilities.addClass(this._upButton, this._iconsCssClass.down);
                   }
               },
               min: {
                 get: function () {
                     return this._min;
                 },
                 set : function (value) {
                     this._min = value;
                 }
               },
               max: {
                   get: function () {
                       return this._max;
                   },
                   set : function (value) {
                       this._max = value;
                   }
               },
               step: {
                   get: function () {
                       return this._step;
                   },
                   set : function (value) {
                       this._step = value;
                   }
               },
               format: {
                   get: function () {
                       return this._format;
                   },
                   set : function (value) {
                       this._format = value;
                   }
               },
               value: {
                   get: function () {
                       return this._value;
                   },
                   set: function (value) {
                       value = this._adjustDecimals(value);
                       this._value = value;
                       this._refresh();
                   }
               },
               decimalPlaces: {
                 get : function () {
                     return this._decimalPlaces;
                 },
                 set: function (value) {
                     this._decimalPlaces = value;
                 }
               },
                icons: {
                  get :function () {
                      return this._icons;
                  },
                  set: function (val) {
                      this._icons = val;
                      this._refreshIcons();
                  }
                },
                iconsCssClass:{
                  get : function () {
                      return this._iconCssClass;
                  },
                  set: function (val) {
                      this._iconCssClass = val;
                      this._refreshIcons();

                  }
                },
               stepUp: function () {
                 
                   this._stepUp(true);
               },
               stepDown: function () {
                 

                   this._stepDown(true);
               }
            })
        });
    
    WinJS.Class.mix(Bixaps.UI.NumericBox,
       WinJS.Utilities.createEventProperties(
        "step",
        "stepup",
        "stepdown"
   ));

})();